4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
11 // You must not remove this notice, or any other, from this software.
16 namespace Microsoft
.JScript
{
19 using System
.Collections
;
20 using System
.Globalization
;
21 using System
.Reflection
;
23 internal sealed class HashtableEntry
{
25 internal Object
value;
26 internal uint hashCode
;
27 internal HashtableEntry next
;
29 internal HashtableEntry(Object key
, Object
value, uint hashCode
, HashtableEntry next
){
32 this.hashCode
= hashCode
;
37 public sealed class SimpleHashtable
{
38 private HashtableEntry
[] table
;
40 private uint threshold
;
42 public SimpleHashtable(uint threshold
){
45 this.table
= new HashtableEntry
[(int)(threshold
* 2 - 1)];
47 this.threshold
= threshold
;
50 public IDictionaryEnumerator
GetEnumerator(){
51 return new SimpleHashtableEnumerator(this.table
);
54 private HashtableEntry
GetHashtableEntry(Object key
, uint hashCode
){
55 int index
= (int)(hashCode
% (uint)this.table
.Length
);
56 HashtableEntry e
= this.table
[index
];
57 if (e
== null) return null;
58 if (e
.key
== key
) return e
;
59 HashtableEntry prev
= e
;
60 HashtableEntry curr
= e
.next
;
67 if (e
.hashCode
== hashCode
&& e
.key
.Equals(key
)){
68 e
.key
= key
; return e
;
73 if (curr
.hashCode
== hashCode
&& curr
.key
.Equals(key
)){
74 curr
.key
= key
; return curr
;
82 internal Object
IgnoreCaseGet(String name
){
83 for (uint i
= 0, n
= (uint)this.table
.Length
; i
< n
; i
++){
84 HashtableEntry e
= this.table
[i
];
86 if (String
.Compare((String
)e
.key
, name
, StringComparison
.OrdinalIgnoreCase
) == 0) return e
.value;
93 private void Rehash(){
94 HashtableEntry
[] oldTable
= this.table
;
95 uint threshold
= this.threshold
= (uint)(oldTable
.Length
+1);
96 uint newCapacity
= threshold
* 2 - 1;
97 HashtableEntry
[] newTable
= this.table
= new HashtableEntry
[newCapacity
];
98 for (uint i
= threshold
-1; i
-- > 0;){
99 for (HashtableEntry old
= oldTable
[(int)i
]; old
!= null; ){
100 HashtableEntry e
= old
; old
= old
.next
;
101 int index
= (int)(e
.hashCode
% newCapacity
);
102 e
.next
= newTable
[index
];
108 public void Remove(Object key
){
109 uint hashCode
= (uint)key
.GetHashCode();
110 int index
= (int)(hashCode
% (uint)this.table
.Length
);
111 HashtableEntry e
= this.table
[index
];
112 Debug
.Assert(e
!= null);
114 while (e
!= null && e
.hashCode
== hashCode
&& (e
.key
== key
|| e
.key
.Equals(key
)))
116 this.table
[index
] = e
;
118 if (e
== null) return;
119 HashtableEntry f
= e
.next
;
120 while (f
!= null && f
.hashCode
== hashCode
&& (f
.key
== key
|| f
.key
.Equals(key
)))
127 public Object
this[Object key
]{
129 HashtableEntry e
= this.GetHashtableEntry(key
, (uint)key
.GetHashCode());
130 if (e
== null) return null;
134 uint hashCode
= (uint)key
.GetHashCode();
135 HashtableEntry e
= this.GetHashtableEntry(key
, hashCode
);
137 e
.value = value; return;
139 if (++this.count
>= this.threshold
) this.Rehash();
140 int index
= (int)(hashCode
% (uint)this.table
.Length
);
141 this.table
[index
] = new HashtableEntry(key
, value, hashCode
, this.table
[index
]);
147 internal sealed class SimpleHashtableEnumerator
: IDictionaryEnumerator
{
148 private HashtableEntry
[] table
;
151 private HashtableEntry currentEntry
;
153 internal SimpleHashtableEnumerator(HashtableEntry
[] table
){
155 this.count
= table
.Length
;
157 this.currentEntry
= null;
160 public Object Current
{ //Used by expando classes to enumerate all the keys in the hashtable
166 public DictionaryEntry Entry
{
168 return new DictionaryEntry(this.Key
, this.Value
);
174 return this.currentEntry
.key
;
178 public bool MoveNext(){
179 HashtableEntry
[] table
= this.table
;
180 if (this.currentEntry
!= null){
181 this.currentEntry
= this.currentEntry
.next
;
182 if (this.currentEntry
!= null)
185 for (int i
= ++this.index
, n
= this.count
; i
< n
; i
++)
186 if (table
[i
] != null){
188 this.currentEntry
= table
[i
];
196 this.currentEntry
= null;
201 return this.currentEntry
.value;